import Rte from 'editor/index'
import { ElementListener, RenderInst } from 'share/declare'
import { reactive, ReactiveInstance } from 'share/reactive'
import { RteLineReactiveMap, RteLineRefs } from './declare'

import 'assets/style/line.scss'
import ast from '!!html-ast-loader!./line.html'
import render from 'share/render'
import { isBr, uuid } from 'share/utils'
import { last } from 'lodash'

export default class RteLine implements RenderInst {
  public $data: ReactiveInstance<RteLineReactiveMap>

  // @ts-ignore
  public $refs: RteLineRefs = {}

  public $listener: ElementListener<RteLine> = {
    insert({ target }) {
      const postion = target.getAttribute('insert')
      this.editor.content.insertLine(this, postion)
    },
    remove() {
      this.editor.content.removeLine(this)
    },
    mouseenter() {
      this.$data.hover = true
    },
    mouseleave() {
      this.$data.hover = false
    },
  }

  public constructor(public editor: Rte, type: string = 'p') {
    this.$data = reactive({
      id: uuid(6, 'rte'),
      type: type,
      focus: false,
      hover: false,
    })

    render(ast, this)
  }

  /**
   * 内容部分以 <br> 结尾
   */
  public endWithBr() {
    const { editable } = this.$refs
    const lastElem = editable.lastElementChild
    if (!lastElem || !isBr(lastElem)) {
      editable.append(document.createElement('br'))
    }
  }

  public children() {
    this.endWithBr()
    const children = Array.from(this.$refs.editable.childNodes)
    children.pop()
    return children
  }

  /**
   * 输入光标定位
   * @param offset 光标偏移量
   */
  public caretIn(offset: number = -1, caret: 'before' | 'after' = 'after') {
    const children = this.children()
    if (typeof offset === 'number' && children.length) {
      if (offset < 0) {
        offset += children.length
      }
      if (offset > children.length) {
        offset = children.length
      }
    } else {
      offset = children.length
    }
    const { root, editable } = this.$refs
    const input = this.editor.input
    const ref = editable.childNodes[offset]

    // 将输入框添加到
    editable.insertBefore(input.$refs.root, ref)

    // 同步段落样式
    input.paragrap.from(editable).from(root)
    // 同步文字样式
    const text = caret === 'before' ? input.$refs.root.previousElementSibling : input.$refs.root.nextElementSibling
    input.text.from(text)

    if (this.editor.$data.contenteditable) {
      this.editor.input.focus()
    }
  }
}
